package com.nfit.shopadmin.service.impl;

import com.nfit.shopadmin.mapper.CartMapper;
import com.nfit.shopadmin.mapper.ProductSkuMapper;
import com.nfit.shopadmin.service.CartService;
import com.nfit.shopcommon.utils.ThreadLocalUtil;
import com.nfit.shopmodel.dto.cart.CartDto;
import com.nfit.shopmodel.entity.cart.CartItem;
import com.nfit.shopmodel.entity.product.ProductSku;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.nfit.shopmodel.vo.common.AuthConst.*;

/**
 * ClassName:CartServiceImpl
 * Package:com.nfit.shopadmin.service.impl
 * Description
 *
 * @Author L
 * @Create 2024/12/31 21:31
 */
@Slf4j
@Schema(description = "购物车业务处理")
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private CartMapper cartMapper;

    @Autowired
    private ProductSkuMapper productSkuMapper;

    /**
     * 添加购物车
     */
    @Override
    public void saveCart(CartDto cartDto) {
        //判断skuId和商品购买数量是否合法
        if (cartDto.getSkuId() == null || cartDto.getCount() == null || cartDto.getCount() <= 0){
            throw new RuntimeException("添加购物车异常信息");
        }
        //从threadLocal获取当前登录的用户id
        String uId = ThreadLocalUtil.get(THREADLOCAL_ADMIN_USER);
//        log.info("移动端登入用户的id:{}",uId);
        //获取不到抛异常
        if (uId.isEmpty()){
            throw new RuntimeException("未获取到用户openId、未登录!不可以添加商品到购物车。");
        }
        //根据商品sku,获取实时库存（数据库中的总库存量,并把信息存入redis中）,调用方法获取库存信息
        Integer RedisStock = this.checkStock(cartDto.getSkuId());
        //判断redis中存储的库存 < 前端传来的购买数量则抛异常
        if (RedisStock < cartDto.getCount()){
            throw new RuntimeException("库存不足，无法添加到购物车！");
        }
        // 从 Redis 查询当前用户添加到购物车的商品是否已存在redis中
        CartItem cartItem = (CartItem) redisTemplate.opsForHash().get(CART_SKU_USER + uId, String.valueOf(cartDto.getSkuId()));
        //判断不为null
        if (cartItem != null){
            // 如果商品已存在，则更新数量
            Integer newCount = cartItem.getSkuCount() + cartDto.getCount();
            //判断的是：之前存储在redis中的购买数量+现在的购买数量 >  数据库中的总库存量
            if (newCount > RedisStock) {
                throw new RuntimeException("库存不足，无法添加更多商品！");
            }
            //封装新的购买商品数量
            cartItem.setSkuCount(newCount);
            //更新redis数据
            redisTemplate.opsForHash().put(CART_SKU_USER+uId, cartDto.getSkuId(), cartItem);
        }else{
            ProductSku productSku = productSkuMapper.getProductSkuInfo(cartDto.getSkuId());
            // 如果商品不存在，则创建新的购物车项
            cartItem = new CartItem();
            cartItem.setSkuId(cartDto.getSkuId()); //skuID
            cartItem.setProductId(productSku.getProductId()); //商品id
            cartItem.setSkuCount(cartDto.getCount()); // 商品购买数量
            cartItem.setSkuStock(RedisStock); // 商品总库存数量
            cartItem.setUserId(Long.valueOf(uId)); //用户id
            cartItem.setSkuName(productSku.getSkuName()); //商品名称
            cartItem.setSpecValue(productSku.getSkuSpec()); //商品规格
            cartItem.setThumbImg(productSku.getThumbImg()); //商品缩略图
            cartItem.setSkuPrice(productSku.getSalePrice()); //商品价格
//            log.info("商品不存在，则创建新的购物车项:{}",cartItem);
            // 将新的购物车项保存到 Redis
            redisTemplate.opsForHash().put(CART_SKU_USER+uId, String.valueOf(cartDto.getSkuId()), cartItem);
        }
        //存储到数据库中
        cartMapper.saveCart(cartItem);
    }

    /**
     * 获取购物车列表
     */
    @Override
    public List<CartItem> getCartList(Long userId) {
        return cartMapper.getCartList(userId);
    }

    /**
     * 根据购物车id删除,逻辑未实现
     */
    @Override
    public void removeCart(Long id) {
        cartMapper.removeCart(id);
    }

    /**
     * 修改商品库存信息,未实现
     * @param skuId skuId
     * @param count 用户购买商品数量
     */
    @Override
    public void modifyProductStock(Long skuId, Integer count) {
        log.info("skuId:{},购买数量count:{}",skuId,count);
        //判断参数是否合法
        if(skuId == null || count == null || count <= 0){
            throw new RuntimeException("修改商品库存信息,参数错误!");
        }

        //查询redis中的商品库存信息
        Integer stock = (Integer) redisTemplate.opsForValue().get(CART_SKU_STOCK + skuId);
        log.info("查询redis中的商品库存信息:{}",stock);
        //判断redis中是否存在库存信息
        if (stock != null){//redis中有库存信息
            //有库存信息,判断库存是否足够
            if (stock < count){
                throw new RuntimeException("库存不足!库存数："+stock+"用户购买量:"+count);
            }
            //库存足够,扣减库存
            stock = stock - count;
            //更新redis中的库存信息
            redisTemplate.opsForValue().set(CART_SKU_STOCK + skuId,stock,60,TimeUnit.SECONDS);
        }else { //redis中没有库存信息
            //查询数据库,获取库存信息
            Integer myStock = this.checkStock(skuId);
            log.info("查询数据库,获取库存信息:{}",myStock);
            //数据库中不存在信息
            if (myStock == null){
                throw new RuntimeException("在数据库中未找到库存信息!");
            }
            //数据库中存在信息,把库存缓存到redis中
            //更新redis中的库存信息
            redisTemplate.opsForValue().set(CART_SKU_STOCK + skuId,myStock,60,TimeUnit.SECONDS);
        }
        //写入数据库中
        productSkuMapper.renewStock(skuId,stock);
    }

    /**
     * 修改购物车商品选中状态-单品商品
     */
    @Override
    public void modifySelected(CartDto cartDto) {
        CartItem cartItem = new CartItem();
        //从线程工具类中获取userId
        String userId = ThreadLocalUtil.get(THREADLOCAL_ADMIN_USER);
        cartItem.setUserId(Long.valueOf(userId));
        cartItem.setSkuId(cartDto.getSkuId());
        if (cartDto.getSelectedStatus()) {
            cartItem.setChecked(1);
        }else {
            cartItem.setChecked(0);
        }
        cartMapper.modifySelected(cartItem);
    }

    /**
     * 修改购物车商品选中状态-全部商品
     */
    @Override
    public void modifySelectedAll(Map<String, Boolean> map) {
        CartItem cartItem = new CartItem();
        //从线程工具类中获取userId
        String userId = ThreadLocalUtil.get(THREADLOCAL_ADMIN_USER);
        cartItem.setUserId(Long.valueOf(userId));
        //获取值状态值
        Boolean selectedStatus = map.get("selectedStatus");
        if (selectedStatus) {
            cartItem.setChecked(1);
        }else {
            cartItem.setChecked(0);
        }
        cartMapper.modifySelectedAll(cartItem);
    }

    /**
     * 根据skuId获取实时的库存数量并存入redis中
     * @param skuId 商品 SKU ID
     * @return 商品的实时库存数量
     */
    private Integer checkStock(Long skuId) {
        //从redis中查询库存信息
        Integer stock = (Integer) redisTemplate.opsForValue().get(CART_SKU_STOCK+skuId.toString());
        //为null，表示redis中没有这个商品sku的库存信息
        if (stock == null){
            // 如果 Redis 中没有库存信息，则查询数据库
            stock = queryStockFromInventoryService(skuId);
            // 将库存存入 Redis，设置适当的过期时间（避免频繁调用接口）,过期时间60mm
            redisTemplate.opsForValue().set(CART_SKU_STOCK+ skuId.toString(),
                    stock, 60, TimeUnit.SECONDS);
        }
        //不为null直接返回查询到的数据
        return stock;
    }

    /**
     * 调用库存服务接口查询库存
     * @param skuId 商品 SKU ID
     * @return 实时库存数量
     */
    private Integer queryStockFromInventoryService(Long skuId) {

        try {
            //返回商品库存数量
            Integer stock = productSkuMapper.getStock(skuId); // 调用库存服务接口
            return stock;
        } catch (Exception e) {
            throw new RuntimeException("库存服务调用失败，请稍后再试！");
        }

    }




}
